package org.zjx.task.repository;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.zjx.task.AbstractTask;
import org.zjx.task.RetryTask;
import org.zjx.task.core.ITask;
import org.zjx.task.core.ITaskChain;
import org.zjx.util.JsonUtils;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class TaskChainGenerator {
    private final TaskRepository taskRepository;
    private final TaskChainRepository chainRepository;

    public TaskChainGenerator(TaskRepository taskRepository,TaskChainRepository chainRepository) {
        this.taskRepository = taskRepository;
        this.chainRepository = chainRepository;
    }

    /**
     * 从JSON配置文件生成多个任务链
     * @param configPath 配置文件路径
     * @return 生成的任务链列表
     * @throws RuntimeException 如果加载配置失败
     */
    public List<ITaskChain> generateChainsFromConfigFile(String configPath) {
        try {
            String configContent = new String(Files.readAllBytes(Paths.get(configPath)));
            return generateChainsFromJson(JSON.parseObject(configContent));
        } catch (IOException e) {
            throw new RuntimeException("Failed to load task chain config: " + configPath, e);
        }
    }

    /**
     * 从JSON字符串生成多个任务链
     * @param jsonString JSON字符串
     * @return 生成的任务链列表
     */
    public List<ITaskChain> generateChainsFromJsonString(String jsonString) {
        return generateChainsFromJson(JSON.parseObject(jsonString));
    }

    /**
     * 从JSON对象生成多个任务链
     * @param config JSON配置对象
     * @return 生成的任务链列表
     */
    public List<ITaskChain> generateChainsFromJson(JSONObject config) {
        List<ITaskChain> chains = new ArrayList<>();

        if (config.containsKey("chains")) {
            JSONArray chainsArray = config.getJSONArray("chains");
            for (int i = 0; i < chainsArray.size(); i++) {
                JSONObject chainConfig = chainsArray.getJSONObject(i);
                ITaskChain chain = generateChainFromJson(chainConfig);
                chains.add(chain);
            }
        }

        return chains;
    }

    /**
     * 从JSON对象生成单个任务链
     * @param config JSON配置对象
     * @return 生成的任务链
     */
    private ITaskChain generateChainFromJson(JSONObject config) {
        String chainId = config.getString("id");
        ITaskChain chain = chainRepository.getChainByClass(chainId);

        if (chain == null) {
            throw new RuntimeException("chain not found: " + chainId);
        }
        // 设置链参数
        if (config.containsKey("params")) {
            chain.setParams(JsonUtils.toMap(config.getJSONObject("params")));
        }

        // 添加任务
        if (config.containsKey("tasks")) {
            JSONArray tasks = config.getJSONArray("tasks");
            for (int i = 0; i < tasks.size(); i++) {
                JSONObject taskConfig = tasks.getJSONObject(i);
                AbstractTask task = createTaskFromConfig(taskConfig);
                chain.addTask(task);
            }
        }

        return chain;
    }

    private AbstractTask createTaskFromConfig(JSONObject taskConfig) {
        String taskId = taskConfig.getString("id");
        AbstractTask task = taskRepository.getTaskByClass(taskId);
        if (task == null) {
            throw new RuntimeException("Task not found: " + taskId);
        }

        // 设置任务参数
        if (taskConfig.containsKey("params")) {
            JSONObject params = taskConfig.getJSONObject("params");
            task.setParams(JsonUtils.toMap(params));
        }

        // 设置重试策略
        if (taskConfig.containsKey("maxRetries")) {
            ((RetryTask)task).setMaxRetries(taskConfig.getInteger("maxRetries"));
        }

        // 设置同步还是异步执行
        if (taskConfig.containsKey("executionStrategy")) {
            ITask.ExecutionStrategy executionStrategy = ITask.ExecutionStrategy.valueOf(taskConfig.getString("executionStrategy"));
            task.setExecutionStrategy(executionStrategy);
        }

        // 设置失败后是否继续
        if (taskConfig.containsKey("failureStrategy")) {
            ITask.FailureStrategy failureStrategy = ITask.FailureStrategy.valueOf(taskConfig.getString("failureStrategy"));
            task.setFailureStrategy(failureStrategy);
        }

        return task;
    }
}
